/*
    Copyright (C) 2008  DiGital <digital7@ukr.net>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

    This program contains code from GNU Wget,
    released under the GNU GPL (http://gnu.org/).
*/

#include <sys/ioctl.h>
#include <sys/types.h> 
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include "settings.c"
#include "daemon.c"

struct DATASTRUCT data[] = {
		// Count of members
		{34,"count", NULL},
		// Buttons
		// Number1
		{64, "a", NULL},
		{256, "b", NULL},
		{32, "c", NULL},
		{128, "d", NULL},
		{320, "ab", NULL},
		{96, "ac", NULL},
		{192, "ad", NULL},
		{288, "bc", NULL},
		{384, "bd", NULL},
		{160, "cd", NULL},
		{352, "abc", NULL},
		{448, "abd", NULL},
		{224, "acd", NULL},
		{416, "bcd", NULL},
		{480, "abcd", NULL},
		// Long presses
		// Number16
		{-1, "along", NULL},
		{-1, "blong", NULL},
		{-1, "clong", NULL},
		{-1, "dlong", NULL},
		{-1, "ablong", NULL},
		{-1, "aclong", NULL},
		{-1, "adlong", NULL},
		{-1, "bclong", NULL},
		{-1, "bdlong", NULL},
		{-1, "cdlong", NULL},
		{-1, "abclong", NULL},
		{-1, "abdlong", NULL},
		{-1, "acdlong", NULL},
		{-1, "bcdlong", NULL},
		{-1, "abcdlong", NULL},
		// Other settings
		// Number31
		{-1, "port", "/dev/ttyS0"},
		{-1, "pidfile", "/var/run/rmpc4.pid"},
		{-1, "uselongclick", "yes"}
	};
	
int pd;
int use_long;
char *config_file = "/etc/rmpc4.conf";
char *procname; //= "rmpc4";
char *procversion = "4.0.4";

extern int get_pid (char **pidfile_path);

int
run_command (int cmdcode)
{
	if (data[cmdcode].command == NULL)
		return 0;

	switch (vfork())
	{
		case 0:
			setsid();
			switch(vfork())
			{
				case 0:				
					execlp ("sh", "sh", "-c", data[cmdcode].command, (char *) NULL);
					_exit(0);
					break;
				default:
					_exit(0);
					break;
			}
			break;
		case -1:
			fprintf(stderr, "%s: Error in vfork()\n", procname);
			break;
		default:
			wait(NULL);
			break;
	}
	return 0;
}
		
int
get_pin_status()
{
	int flags = 0, state_on = 0;
	ioctl (pd, TIOCMGET, &flags);

	state_on += (flags & TIOCM_CAR);
	state_on += (flags & TIOCM_DSR);
	state_on += (flags & TIOCM_CTS);
	state_on += (flags & TIOCM_RNG);

	return state_on;
}

int
check_buttons()
{
	int i;
	int was_long;
	int buttons_state = 0;
	while(1)
	{
		was_long = 0;
		buttons_state = get_pin_status();
		for (i=1; i <= 15; i++)
		{
			if (data[i].code == buttons_state)
			{
				if (use_long)
				{
					usleep (200000);
					while ((buttons_state = get_pin_status()) && (data[i].code == buttons_state))
					{
						run_command(i+15);
						was_long = 1;
						usleep (100000);
					}
				}
				
				if (!was_long)
				{
					run_command (i);
					usleep (150000);
				}

				break;
			}
		}
		usleep (50000);
	}
}

void
dohelp()
{
	fprintf (stdout, "%s version %s. Usage:\n\n", procname, procversion);

	fprintf (stdout, "\t--help\t\t - this help\n");
	fprintf (stdout, "\t--kill\t\t - kill daemon\n");
	fprintf (stdout, "\t--killforce\t - kill daemon forced (Not recommended)\n");
	fprintf (stdout, "\t--nodaemon\t - don't use daemon. Start in foreground.\n");
	fprintf (stdout, "\t-f <file>\t - use alternate configuration file\n");
	fprintf (stdout, "\nPlease, report any bugs to <digital7@ukr.net>\n");
}




int
main (int argc, char** argv){
	int nodaemon = 0;
	int k;
	pid_t m_pid;

	procname = (char*)malloc(sizeof(char) * (strlen(argv[0])+1));
	strcpy(procname, argv[0]);

	if (argc != 0)
	{
		for (k = 0; k < argc; k++)
		{
			if (strcasecmp(argv[k], "--help") == 0)
			{
				dohelp();
				return 0;
			}
	
			if (strcasecmp(argv[k], "--kill") == 0)
			{
				get_settings();
				int pid = get_pid(&data[32].command);
				if (pid)
				{
					kill (pid, SIGTERM);
					remove (data[32].command);
					return 0;
				}
				fprintf (stderr, "%s: Error reading PID-file. Is %s running?\n", procname, procname);
				return 1;
			}

			if (strcasecmp(argv[k], "--killforce") == 0)
			{
				char *cmd = (char *)malloc (sizeof(char) * (strlen(procname) + 8 + 1));
				strcpy (cmd, "killall ");
				strcat (cmd, procname);
				execlp ("sh", "sh", "-c", cmd, (char *) NULL);
				return 0;
			}
	
			if (strcasecmp(argv[k], "-f") == 0)
			{
				config_file = (char *)malloc (sizeof(char) * (strlen(argv[k+1])+1));
				strcpy (config_file, argv[k+1]);
				k++;
			}

			if (strcasecmp(argv[k], "--nodaemon") == 0)
				nodaemon = 1;
		}
	}

	get_settings();
	if (!nodaemon)
	{

		int pid = get_pid(&data[32].command);
		if (pid)
		{
			fprintf(stderr, "%s: Another copy of %s with PID %d is running!.\n", procname, procname, pid);
			return 1;
		}

		m_pid = fork();
		switch (m_pid)
		{
			case 0: // Child
				break;
			case -1: // Error
				fprintf (stderr, "%s: Error in fork()\n", procname);
				return 1;
			default:
				write_pid (&data[32].command, m_pid);
				return 0;
		}

	}
	pd = open(data[31].command, O_RDONLY);
	if (pd == -1)
	{
		fprintf (stderr, "%s: Port opening error. Chech your settings and permissions.\n", procname);
		return 1;
	}
	if (strcasecmp(data[33].command, "yes") == 0)
			use_long = 1;
	check_buttons();
	return 0;
}

